Infoteam Blog
소개지원 바로가기

컨테이너에서 탈출한 블로그

기존에 Next.js로 작업 되어있던 블로그는 SSR이어서 서버가 있어야지만 서비스를 구동할 수 있는 형태였습니다
하지만 자주 업데이트 되지 않는 블로그의 특성상, 굳이 SSR을 사용하는 것을 리소스 소모가 큽니다.
 
그래서 SSG (Static Site Generation)을 할 수 있는 방법을 알아보았고, 기존의 코드를 재활용하기 위해 Next.js를 Static export 모드로 사용하여 서버 없이 정적 콘텐츠만 서빙할 수 있도록 변경하였습니다.
 

Static Site Generation

Static Site Generation은 한글로 정적 사이트 생성으로 불리며, SPA인 React 앱 관점에서 바라본다면 SPA의 모든 페이지를 각각의 html 파일로 분할해서 빌드하는 방식을 뜻합니다.
사용자의 데이터를 기반으로 동적인 데이터를 서빙하는 것이 아닌, 이미 빌드 타임에 어떤 페이지, 어떤 정보를 알려주어야 할지를 알고 있다면 Static Site Generation을 사용할 수 있습니다.
 

Static Exports in Next.js

Next.js는 기본적으로 SSR으로 돌아가는 프레임워크이지만, next.config.js 파일의 outputexport 로 명시해주면 static export를 만들 수 있습니다.
이렇게하면 Next.js가 클라이언트 쪽의 번들 크기를 줄여주는 장점도 가져가면서 React를 사용한 SSG 사이트를 편하게 만들 수 있습니다.
 
당연히 SSR이 비활성화 되기 때문에 기능이 제한 됩니다.
Feb 2, 2026(16.1.6) 기준으로 제한 되어있는 기능은 아래와 같습니다.
  • dynamicParams: true 인 Dynamic Routes
  • generateStaticParams() 를 사용하지 않는 Dynamic Routes
  • Request에 대응하는 Route Handlers
    • 결과만 돌려주는 GET route handler는 작성 가능합니다.
  • Cookies
  • Rewrites
  • Redirects
  • Headers
  • Proxy
  • ISR (Incremental Static Regeneration)
  • Image Optimization
  • Draft Mode
  • Server Actions
  • Intercepting Routes
 
각 게시글은 /article/[id]/[title]/page.tsx 를 통해 서빙되고 있는데, 이때 빌드 타임에 어떤 페이지들이 존재하는지 알아야하기 때문에 generateStaticParams 함수를 작성해야 합니다.
 
인포팀 블로그에서는 노션과 연동하여 블로그를 작성하게 하고 있기 때문에 notion api를 사용해서 데이터를 가져온 다음에 이를 static params로 만들고 있습니다.
 
export async function generateStaticParams() { const data = await getNotionData(null, null); const result = data.flatMap((page) => [ { id: page.id, title: encodeURI(getTitle(page)), }, { id: page.id, title: getTitle(page), }, ]); return result; }
정적 파일 서빙 서비스마다 파일을 해석하는 방식이 달라서 encodeURI가 된 버전과 안 된 버전 모두 param으로 생성하고 있습니다.
 

Deploy

인포팀은 정적 파일 서빙에 Cloudflare Pages를 사용하고 있습니다.
인프라 관리는 terraform을 사용하기 때문에 terraform에 Pages를 추가해 줍니다.
// ... "blog-fe" = { domain = "blog.gistory.me" production_branch = "main" repository = "blog-fe" build_config = { build_command = "bun install && bun run build", destination_dir = "out" } env = { SKIP_DEPENDENCY_INSTALL = "true" NOTION_DATA_SOURCE_ID = "544b4b2a-0f47-4a61-a8a8-03ce367b53b4" } secret = { NOTION_SECRET_KEY = var.notion_secret_key } } // ...
그러면 배포된 페이지를 확인할 수 있습니다.
 

Update

Cloudflare pages를 사용한 배포는 기본적으로 코드가 변경될 때만 빌드 됩니다.
하지만 블로그 콘텐츠는 코드 변경 없이도 노션에서 계속 수정 되기 때문에 이를 개선해야 합니다.
노션과 연동할 수 있는 pipedream을 사용해서 노션의 콘텐츠 변화를 감지하고, Cloudflare의 deploy hook을 사용해서 콘텐츠가 변경된 경우 배포를 트리거 할 수 있게 하였습니다.
notion image
 

인포팀에서 함께 일하고 싶다면?

지원 바로가기